﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Teigha.DatabaseServices;
using Teigha.Geometry;

namespace SRB.Tg.DrawingStandard
{
    public class MathExtensions
    {
        /// <summary>
        /// 计算两条直线的交点
        /// </summary>
        /// <param name="lineFirstStar">L1的点1坐标</param>
        /// <param name="lineFirstEnd">L1的点2坐标</param>
        /// <param name="lineSecondStar">L2的点1坐标</param>
        /// <param name="lineSecondEnd">L2的点2坐标</param>
        /// <returns></returns>
        public static Point3d GetIntersection(Line line1, Line line2)
        {
            Point3d lineFirstStar = line1.StartPoint;
            Point3d lineFirstEnd = line1.EndPoint;
            Point3d lineSecondStar = line2.StartPoint;
            Point3d lineSecondEnd = line2.EndPoint;
            /*
             * L1，L2都存在斜率的情况：
             * 直线方程L1: ( y - y1 ) / ( y2 - y1 ) = ( x - x1 ) / ( x2 - x1 ) 
             * => y = [ ( y2 - y1 ) / ( x2 - x1 ) ]( x - x1 ) + y1
             * 令 a = ( y2 - y1 ) / ( x2 - x1 )
             * 有 y = a * x - a * x1 + y1   .........1
             * 直线方程L2: ( y - y3 ) / ( y4 - y3 ) = ( x - x3 ) / ( x4 - x3 )
             * 令 b = ( y4 - y3 ) / ( x4 - x3 )
             * 有 y = b * x - b * x3 + y3 ..........2
             * 
             * 如果 a = b，则两直线平等，否则， 联解方程 1,2，得:
             * x = ( a * x1 - b * x3 - y1 + y3 ) / ( a - b )
             * y = a * x - a * x1 + y1
             * 
             * L1存在斜率, L2平行Y轴的情况：
             * x = x3
             * y = a * x3 - a * x1 + y1
             * 
             * L1 平行Y轴，L2存在斜率的情况：
             * x = x1
             * y = b * x - b * x3 + y3
             * 
             * L1与L2都平行Y轴的情况：
             * 如果 x1 = x3，那么L1与L2重合，否则平等
             * 
            */
            double a = 0, b = 0;
            int state = 0;
            if (lineFirstStar.X != lineFirstEnd.X)
            {
                a = (lineFirstEnd.Y - lineFirstStar.Y) / (lineFirstEnd.X - lineFirstStar.X);
                state |= 1;
            }
            if (lineSecondStar.X != lineSecondEnd.X)
            {
                b = (lineSecondEnd.Y - lineSecondStar.Y) / (lineSecondEnd.X - lineSecondStar.X);
                state |= 2;
            }
            switch (state)
            {
                case 0: //L1与L2都平行Y轴
                    {
                        if (lineFirstStar.X == lineSecondStar.X)
                        {
                            //throw new Exception("两条直线互相重合，且平行于Y轴，无法计算交点。");
                            return new Point3d(0, 0,0);
                        }
                        else
                        {
                            //throw new Exception("两条直线互相平行，且平行于Y轴，无法计算交点。");
                            return new Point3d(0, 0, 0);
                        }
                    }
                case 1: //L1存在斜率, L2平行Y轴
                    {
                        double x = lineSecondStar.X;
                        double y = (lineFirstStar.X - x) * (-a) + lineFirstStar.Y;
                        return new Point3d(x, y, 0);
                    }
                case 2: //L1 平行Y轴，L2存在斜率
                    {
                        double x = lineFirstStar.X;
                        double y = (lineSecondStar.X - x) * (-b) + lineSecondStar.Y;
                        return new Point3d(x, y, 0);
                    }
                case 3: //L1，L2都存在斜率
                    {
                        if (a == b)
                        {
                            // throw new Exception("两条直线平行或重合，无法计算交点。");
                            return new Point3d(0, 0, 0);
                        }
                        double x = (a * lineFirstStar.X - b * lineSecondStar.X - lineFirstStar.Y + lineSecondStar.Y) / (a - b);
                        double y = a * x - a * lineFirstStar.X + lineFirstStar.Y;
                        return new Point3d(x, y, 0);
                    }
            }
            // throw new Exception("不可能发生的情况");
            return new Point3d(0, 0, 0);
        }
        #region 直线与圆弧交点
        /// <summary>
        /// 计算直线和圆弧交点方法
        /// </summary>
        /// <param name="line">线段对象</param>
        /// <param name="arc">圆对象</param>
        /// <param name="ht">存储交点和error信息</param>
        /// <returns>返回ht集合</returns>
        public static void LineIntersectArc(Line line, Arc arc, ref List<Point3d> node)
        {
            //得到线段起始点
            Point3d LineStartPoint = line.StartPoint;
            //得到线段的终点
            Point3d LineEndPoint = line.EndPoint;
            //得到弧心坐标
            Point3d vector = arc.Center;
            //起始角度
            double startAngle = arc.StartAngle;
            //终止角度
            double endAngle = arc.EndAngle;
            //得到半径
            double rad = arc.Radius;
            //圆弧的顺逆
            //bool _direction = arc.;
            //假设默认交点坐标
            Point3d ptInter1 = new Point3d(0, 0, 0);
            Point3d ptInter2 = new Point3d(0, 0, 0);
            double X = LineEndPoint.X - LineStartPoint.X;
            double Y = LineEndPoint.Y - LineStartPoint.Y;
          
                //计算得到交点坐标方法
            LineInterCircle(new Point3d(LineStartPoint.X , LineStartPoint.Y, 0), new Point3d(LineEndPoint.X , LineEndPoint.Y, 0), vector, rad * rad, ref ptInter1, ref ptInter2);
         
            //用于存储交点
            node = new List<Point3d>();
            if (ptInter2 != new Point3d(0, 0, 0) && ptInter1 != new Point3d(0, 0, 0))
            {
                //if (X > 0)
                //{
                //    if ((LineStartPoint.X < ptInter2.X && LineEndPoint.X > ptInter2.X) && (LineStartPoint.X < ptInter1.X && LineEndPoint.X > ptInter1.X))
                //    {
                //        node.Add(ptInter1);
                //        node.Add(ptInter2);
                //    }
                //}
                //else
                //{
                //    if ((LineEndPoint.X < ptInter2.X && LineStartPoint.X < ptInter2.X) && (LineEndPoint.X < ptInter1.X && LineStartPoint.X < ptInter1.X))
                //    {
                //        node.Add(ptInter2);
                //        node.Add(ptInter1);
                //    }
                //}
                node.Add(ptInter1);
                node.Add(ptInter2);

            }
            //else if (ptInter2 != new Point3d(0, 0, 0))
            //{
            //    node.Add(ptInter2);
            //}
            //else if (ptInter1 != new Point3d(0, 0, 0))
            //{
            //    node.Add(ptInter1);
            //}
            //用于判断是否有交点
            bool judgeNode = false;
            if (Zero(ptInter1))
            {
                //JudgeDotQualified(vector, ptInter1, startAngle, endAngle,ref node);
                judgeNode = true;
            }
            if (Zero(ptInter2))
            {
                //JudgeDotQualified(vector, ptInter2, startAngle, endAngle, ref node);
                judgeNode = true;
            }

        }


        public static void LineIntersectArcNew(Line line, Arc arc, ref List<Point3d> node)
        {
            //得到线段起始点
            Point3d LineStartPoint = line.StartPoint;
            //得到线段的终点
            Point3d LineEndPoint = line.EndPoint;
            //得到弧心坐标
            Point3d vector = arc.Center;
            //起始角度
            double startAngle = arc.StartAngle;
            //终止角度
            double endAngle = arc.EndAngle;
            //得到半径
            double rad = arc.Radius;

            Arc arc1 = new Arc(arc.Center, arc.Radius, arc.StartAngle, arc.EndAngle);
            Extents2d ext = new Extents2d(arc.StartPoint.C2D(), arc.EndPoint.C2D());
            ext = ext.Add(new Extents2d(arc1.Bounds.Value.MinPoint.C2D(), arc1.Bounds.Value.MaxPoint.C2D()));
            //圆弧的顺逆
            //bool _direction = arc.;
            //假设默认交点坐标
            Point3d ptInter1 = new Point3d(0, 0, 0);
            Point3d ptInter2 = new Point3d(0, 0, 0);
            double X = LineEndPoint.X - LineStartPoint.X;
            double Y = LineEndPoint.Y - LineStartPoint.Y;

            //计算得到交点坐标方法
            LineInterCircle(new Point3d(LineStartPoint.X-X, LineStartPoint.Y-Y, 0), new Point3d(LineEndPoint.X+X, LineEndPoint.Y+Y, 0), vector, rad * rad, ref ptInter1, ref ptInter2);

            //用于存储交点
            node = new List<Point3d>();
            if (ptInter2 != new Point3d(0, 0, 0) && ptInter1 != new Point3d(0, 0, 0))
            {
                if (arc1.Bounds.Value.MinPoint.X <= ptInter1.X&& arc1.Bounds.Value.MaxPoint.X>= ptInter1.X && arc1.Bounds.Value.MinPoint.Y <= ptInter1.Y && arc1.Bounds.Value.MaxPoint.Y >= ptInter1.Y)
                {
                    node.Add(ptInter1);
                }
                if (arc1.Bounds.Value.MinPoint.X <= ptInter2.X && arc1.Bounds.Value.MaxPoint.X >= ptInter2.X && arc1.Bounds.Value.MinPoint.Y <= ptInter2.Y && arc1.Bounds.Value.MaxPoint.Y >= ptInter2.Y)
                {
                    node.Add(ptInter2);
                }
                //node.Add(ptInter1);
                //node.Add(ptInter2);

            }
            //else if (ptInter2 != new Point3d(0, 0, 0))
            //{
            //    node.Add(ptInter2);
            //}
            //else if (ptInter1 != new Point3d(0, 0, 0))
            //{
            //    node.Add(ptInter1);
            //}
            //用于判断是否有交点
            bool judgeNode = false;
            if (Zero(ptInter1))
            {
                //JudgeDotQualified(vector, ptInter1, startAngle, endAngle,ref node);
                judgeNode = true;
            }
            if (Zero(ptInter2))
            {
                //JudgeDotQualified(vector, ptInter2, startAngle, endAngle, ref node);
                judgeNode = true;
            }

        }

        /// <summary>
        /// 直线和圆的交点
        /// </summary>
        /// <param name="ptStart">线段起点</param>
        /// <param name="ptEnd">线段终点</param>
        /// <param name="ptCenter">圆心坐标</param>
        /// <param name="Radius2">圆半径平方</param>
        /// <param name="ptInter1">交点1(若不存在返回0)</param>
        /// <param name="ptInter2">交点2(若不存在返回0)</param>
        public static bool LineInterCircle(Point3d ptStart, Point3d ptEnd, Point3d ptCenter, double Radius2,
           ref Point3d ptInter1, ref Point3d ptInter2)
        {
            double EPS = 0.00001;
            //求线段的长度
            double fDis = System.Math.Sqrt((ptEnd.X - ptStart.X) * (ptEnd.X - ptStart.X) + (ptEnd.Y - ptStart.Y) * (ptEnd.Y - ptStart.Y));
            Point3d d = new Point3d((ptEnd.X - ptStart.X) / fDis, (ptEnd.Y - ptStart.Y) / fDis, 0);

            Point3d E = new Point3d(ptCenter.X - ptStart.X, ptCenter.Y - ptStart.Y, 0);

            double a = E.X * d.X + E.Y * d.Y;
            double a2 = a * a;
            double e2 = E.X * E.X + E.Y * E.Y;
            if ((Radius2 - e2 + a2) < 0)
            {
                return false;
            }
            else
            {
                double f = System.Math.Sqrt(Radius2 - e2 + a2);
                double t = a - f;
                if (((t - 0.0) > -EPS) && (t - fDis) < EPS)
                {
                    ptInter1 = new Point3d(ptStart.X + t * d.X, ptStart.Y + t * d.Y, 0);

                }
                t = a + f;
                if (((t - 0.0) > -EPS) && (t - fDis) < EPS)
                {
                    ptInter2 = new Point3d(ptStart.X + t * d.X, ptStart.Y + t * d.Y, 0);
                }
                return true;
            }
        }

        /// <summary>
        /// 判断点是否为(0,0)
        /// </summary>
        /// <param name="dot">交点</param>
        /// <returns>是(0，0)返回false</returns>
        internal static bool Zero(Point3d dot)
        {
            if (dot.X == 0)
            {
                if (dot.Y == 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// 判断交点是否合格方法
        /// </summary>
        /// <param name="vector">中心圆心</param>
        /// <param name="ptInter1">交点</param>
        /// <param name="startAngle">圆弧起始角度</param>
        /// <param name="endAngle">圆弧终止角度</param>
        /// <param name="node">存放交点集合</param>
        /// <param name="_direction">圆弧得顺逆，默认为逆时针</param>
        internal static void JudgeDotQualified(Point3d vector, Point3d ptInter1, double startAngle, double endAngle,ref List<Point3d> node, bool _direction = false)
        {
            if (!_direction)
            {
                //画弧为逆时针
                //得到一个交点对应的弧度
                double radian = Tangent(vector, ptInter1);
                if (startAngle > endAngle)
                { //起始角度大于终止角度时,交点角度小于终止角度或者交点角度大于起始角度就会与圆弧相交
                    if (radian <= endAngle || radian >= startAngle)
                    {
                        node.Add(ptInter1);
                    }
                }
                else
                { //起始角度小于终止角度时，交点角度在起始角度和终止角度之间就会与圆弧相交
                    if (startAngle < radian && radian < endAngle)
                    {
                        node.Add(ptInter1);
                    }
                    else if (startAngle == radian || endAngle == radian)
                    {
                        node.Add(ptInter1);
                    }
                }
            }
            else
            {
                //画弧为顺时针
                //得到一个交点对应的弧度
                double radian = Tangent(vector, ptInter1);
                if (startAngle < endAngle)
                { //起始角度小于终止角度时,交点角度大于终止角度或者交点角度小于起始角度就会与圆弧相交
                    if (radian <= startAngle || radian >= endAngle)
                    {
                        node.Add(ptInter1);
                    }
                }
                else
                { //起始角度大于终止角度时，交点角度在终止角度和起始角度之间就会与圆弧相交
                    if (endAngle < radian && radian < startAngle)
                    {
                        node.Add(ptInter1);
                    }
                    else if (startAngle == radian || endAngle == radian)
                    {
                        node.Add(ptInter1);
                    }
                }
            }
        }

        /// <summary>
        /// 利用正切值
        /// 计算交点对应的弧度
        /// </summary>
        /// <param name="vector">圆心坐标</param>
        /// <param name="intersect">交点坐标</param>
        /// <returns>弧度</returns>
        public static double Tangent(Point3d vector, Point3d intersect)
        {
            //圆心的x ,y 坐标
            double vectorX = vector.X;
            double vectorY = vector.Y;
            //交点的  x ,y 坐标
            double intersectX = intersect.X;
            double intersectY = intersect.Y;
            //两点的x轴的差值
            double difX = intersectX - vectorX;
            //两点的y轴的差值
            double difY = intersectY - vectorY;
            if (intersectY == vectorY && intersectX > 0)
            {
                //交点在正x轴上,角度为0，弧度为零
                return 0;
            }
            else if (intersectX == vectorX && intersectY > 0)
            {
                //交点在正y轴上，角度为90度
                return DegreeToRadian(90);
            }
            else if (intersectY == vectorY && intersectX < 0)
            {
                //交点在负x轴上，角度为180度
                return DegreeToRadian(180);
            }
            else if (intersectX == vectorX && intersectY < 0)
            {
                //交点在负数y轴上,角度为270度
                return DegreeToRadian(270);
            }
            else
            {
                if (difX > 0 && difY > 0)
                {
                    //锐角
                    double number = difY / difX;
                    return TangentToDegree(number);
                }
                else if (difX < 0 && difY > 0)
                {
                    //小于180度的钝角
                    double number = difY / (-difX);
                    return DegreeToRadian(180) - TangentToDegree(number);
                }
                else if (difX < 0 && difY < 0)
                {
                    //大于180度小于270度的钝角
                    double number = (-difY) / (-difX);
                    return TangentToDegree(number) + DegreeToRadian(180);
                }
                else
                {
                    //(difX > 0 && difY < 0)
                    //大于270度小于360度的钝角
                    double number = (-difY) / difX;
                    return DegreeToRadian(360) - TangentToDegree(number);
                }
            }
        }
        /// <summary>
        /// 角度转弧度
        /// </summary>
        /// <param name="angle">角度</param>
        /// <returns>弧度</returns>
        public static double DegreeToRadian(double angle)
        {
            return ((angle * System.Math.PI) / 180.0);
        }
        /// <summary>
        /// 正切值转弧度
        /// </summary>
        /// <returns>返回一个弧度</returns>
        public static double TangentToDegree(double tangent)
        {
            //得到正切值对应的弧度
            return System.Math.Atan(tangent);
        }
        #endregion

        #region 判断三点是否共线-即三角形面积为0
        public static bool isPointOnSegment(PointF p, PointF p1, PointF p2)
        {
            //[Ax * (By - Cy) + Bx * (Cy - Ay) + Cx * (Ay - By) ]/2 
            //判断三角形面积是否为0
            return p.X * (p1.Y - p2.Y) + p1.X * (p2.Y - p.Y) + p2.X * (p.Y - p1.Y) < 1;
        }

        public static bool isPointOnSegment(Point3d p, Point3d p1, Point3d p2)
        {
            return isPointOnSegment(new PointF((float)p.X, (float)p.Y), new PointF((float)p1.X, (float)p1.Y), new PointF((float)p.X, (float)p.Y));
        }
        public static bool isPointOnSegment(Point2d p, Point2d p1, Point3d p2)
        {
            return isPointOnSegment(new PointF((float)p.X, (float)p.Y), new PointF((float)p1.X, (float)p1.Y), new PointF((float)p.X, (float)p.Y));
        }
        #endregion

        #region 判断两条直线是否相互垂直
        /// <summary>
        /// 直线垂直
        /// </summary>
        /// <param name="Lin1"></param>
        /// <param name="Lin2"></param>
        /// <returns></returns>
        public static bool ISInLine(LineSegment2d Lin1, Line Lin2)
        {
            if (Math.Round(((Lin1.EndPoint.Y - Lin1.StartPoint.Y) / (Lin1.EndPoint.X - Lin1.StartPoint.X)) *
                ((Lin2.EndPoint.Y - Lin2.StartPoint.Y) / (Lin2.EndPoint.X - Lin2.StartPoint.X)), 5) == -1)
                return true;
            else
                return false;
        }



        public static bool ISInLine(Line Lin1, Line Lin2)
        {
            if (Math.Round(((Lin1.EndPoint.Y - Lin1.StartPoint.Y) / (Lin1.EndPoint.X - Lin1.StartPoint.X)) *
                ((Lin2.EndPoint.Y - Lin2.StartPoint.Y) / (Lin2.EndPoint.X - Lin2.StartPoint.X)), 5) == -1)
                return true;
            else
                return false;
        }
        #endregion

        #region 圆与直线的交点
        /// <summary>
        /// 圆与直线的交点
        /// </summary>
        /// <param name="cx"></param>
        /// <param name="cy"></param>
        /// <param name="r"></param>
        /// <param name="stx"></param>
        /// <param name="sty"></param>
        /// <param name="edx"></param>
        /// <param name="edy"></param>
        /// <returns></returns>
        public static Point3d GetPoint(double cx, double cy, double r, double stx, double sty, double edx, double edy)
        {
            //(x - cx )^2 + (y - cy)^2 = r^2
            //y = kx +b

            //求得直线方程
            double k = (edy - sty) / (edx - stx);
            double b = edy - k * edx;

            //列方程
            /*
              (1 + k^2)*x^2 - x*(2*cx -2*k*(b -cy) ) + cx*cx + ( b - cy)*(b - cy) - r*r = 0
            */
            double x1, y1, x2, y2;
            double c = cx * cx + (b - cy) * (b - cy) - r * r;
            double a = (1 + k * k);
            double b1 = (2 * cx - 2 * k * (b - cy));
            //得到下面的简化方程
            // a*x^2 - b1*x + c = 0;

            double tmp = Math.Sqrt(b1 * b1 - 4 * a * c);
            x1 = (b1 + tmp) / (2 * a);
            y1 = k * x1 + b;
            x2 = (b1 - tmp) / (2 * a);
            y2 = k * x2 + b;

            //判断求出的点是否在圆上

            double res = (x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy);
            Point3d p = new Point3d();
            if ((int)res == (int)(r * r))  //我这里 r = 50,res = 2500.632,还是比较准确的
            {
                p = new Point3d(x1, y1, 0);
            }
            else
            {
                p = new Point3d(x2, y2, 0);

            }
            return p;
        }

        #endregion


        #region 判断直线是否与当前圆相交
        /// <summary>
        /// 判断直线是否与当前圆相交
        /// </summary>
        /// <param name="Center"></param>
        /// <param name="Lin"></param>
        /// <returns></returns>
        public static bool ISInArcLine(Point2d Center, Line Lin)
        {
            double LenCha = Math.Abs(Math.Sqrt(
                (Lin.StartPoint.X - Center.X) * (Lin.StartPoint.X - Center.X) + (Lin.StartPoint.Y - Center.Y) * (Lin.StartPoint.Y - Center.Y)
                ) -
                Math.Sqrt(
                (Lin.EndPoint.X - Center.X) * (Lin.EndPoint.X - Center.X) + (Lin.EndPoint.Y - Center.Y) * (Lin.EndPoint.Y - Center.Y)
                ))
                ;
            if (Math.Round(LenCha, 12) == Math.Round(Lin.Length, 12))
                return true;
            else
                return false;
        }
        #endregion

        #region 求圆弧长度
        /// <summary>
        /// 求弧长
        /// </summary>
        /// <param name="Angle"></param>
        /// <returns></returns>
        public static double ArcLengthFormula(double Angle, double R)
        {
            double l = (Angle * Math.PI * R) / 180;
            return l;
        }

        public static double ArcLengthFormula(Point2d cen, Point2d first, Point2d second, double R)
        {
            double Ang = Angle(new Point3d(cen.X, cen.Y, 0), new Point3d(first.X, first.Y, 0), new Point3d(second.X, second.Y, 0));
            double l = (Ang * Math.PI * R) / 180;
            return l;
        }

        public static double ArcLengthFormula(Point3d cen, Point3d first, Point3d second, double R)
        {
            double Ang = Angle(new Point3d(cen.X, cen.Y, 0), new Point3d(first.X, first.Y, 0), new Point3d(second.X, second.Y, 0));
            double l = (Ang * Math.PI * R) / 180;
            return l;
        }


        #endregion

        #region 获取圆弧上指定长度的点
        /// <summary>
        /// 获取圆弧上指定长度的点
        /// </summary>
        /// <param name="Center">圆心</param>
        /// <param name="Strted">开始</param>
        /// <param name="Ended">介素</param>
        /// <param name="ArcLen">圆弧长度</param>
        /// <param name="IsClockWise">是否顺时针</param>
        /// <param name="NedLen">指定的长度</param>
        /// <returns></returns>
        public static Point3d getApointOnTheArc(Point3d Center, Point3d Strted, Point3d Ended, double ArcLen, bool IsClockWise, double NedLen)
        {
            //圆弧所对应的圆心角度
            double Angles = Angle(Center, Strted, Ended);
            //指定长度段的圆心角度
            double n_Ang = (NedLen * Angles) / ArcLen;

            //顺时针还是逆时针
            if (IsClockWise)
            {
                double x = (Strted.X - Center.X);
                double y = (Strted.Y - Center.Y);
                double x1 = x * Math.Cos(n_Ang * Math.PI / 180) + y * Math.Sin(n_Ang * Math.PI / 180) + Center.X;
                double y1 = y * Math.Cos(n_Ang * Math.PI / 180) - x * Math.Sin(n_Ang * Math.PI / 180) + Center.Y;
                return new Point3d(x1, y1, 0);
            }
            else
            {
                double x = (Strted.X - Center.X);
                double y = (Strted.Y - Center.Y);
                double x1 = x * Math.Cos(n_Ang * Math.PI / 180) - y * Math.Sin(n_Ang * Math.PI / 180) + Center.X;
                double y1 = x * Math.Sin(n_Ang * Math.PI / 180) + y * Math.Cos(n_Ang * Math.PI / 180) + Center.Y;
                return new Point3d(x1, y1, 0);
            }
        }

        #endregion

        #region 已知三点求夹角（锐角）

        //已知三点坐标，求夹角
        public static double Angle(Point3d cen, Point3d first, Point3d second)
        {
            double M_PI = Math.PI;
            double ma_x = first.X - cen.X;
            double ma_y = first.Y - cen.Y;
            double mb_x = second.X - cen.X;
            double mb_y = second.Y - cen.Y;
            double v1 = (ma_x * mb_x) + (ma_y * mb_y);
            double ma_val = Math.Sqrt(ma_x * ma_x + ma_y * ma_y);
            double mb_val = Math.Sqrt(mb_x * mb_x + mb_y * mb_y);
            double cosM = v1 / (ma_val * mb_val);
            double angleAMB = Math.Acos(cosM) * 180 / M_PI;
            return angleAMB;
        }

        public static double Angle(Point cen, Point first, Point second)
        {
            return Angle(new Point3d(cen.X, cen.Y, 0), new Point3d(first.X, first.Y, 0), new Point3d(second.X, second.Y, 0));
        }


        #endregion

        #region 任意点(x,y)，绕一个坐标点(rx0,ry0)逆时针旋转a角度后的新的坐标(x0, y0)，
        /// <summary>
        /// 任意点(x,y)，绕一个坐标点(rx0,ry0)逆时针旋转a角度后的新的坐标设为(x0, y0)，
        /// </summary>
        /// <param name="PoCenter"></param>
        /// <param name="Rauis"></param>
        /// <param name="Angle"></param>
        /// <returns></returns>
        public static Point3d GetJiaodian(Point3d PoCenter, Point3d PoFrist, double Angle)
        {
            double x0 = (PoFrist.X - PoCenter.X) * Math.Cos(Angle) - (PoFrist.Y - PoCenter.Y) * Math.Sin(Angle) + PoCenter.X;
            double y0 = (PoFrist.X - PoCenter.X) * Math.Sin(Angle) + (PoFrist.Y - PoCenter.Y) * Math.Cos(Angle) + PoCenter.Y;
            return new Point3d(x0, y0, 0);
        }

        #endregion

        #region 获取直线反向延长指定长度的坐标
        /// <summary>
        /// 获取直线反向延长指定长度的坐标
        /// </summary>
        /// <param name="curPoint"></param>
        /// <param name="nextPoint"></param>
        /// <param name="L"></param>
        /// <returns></returns>
        public static Point3d GetExtend_specified_length(Point3d curPoint, Point3d nextPoint, double L)
        {
            //double distance = Math.Sqrt(Math.Pow(curPoint.X - nextPoint.X, 2)
            //    + Math.Pow(curPoint.Y - nextPoint.Y, 2));// 两点的坐标距离
            //double lenthUnit = distance / 5;// 单位长度
            // 第一步：求得直线方程相关参数y=kx+b
            double k = (curPoint.Y - nextPoint.Y) * 1.0
                    / (curPoint.X - nextPoint.X);// 坐标直线斜率k
            double b = curPoint.Y - k * curPoint.X;// 坐标直线b
                                                   // 第二步：求得在直线y=kx+b上，距离当前坐标距离为L的某点
                                                   // 一元二次方程Ax^2+Bx+C=0中,
                                                   // 一元二次方程求根公式：
                                                   // 两根x1,x2= [-B±√(B^2-4AC)]/2A
                                                   // ①(y-y0)^2+(x-x0)^2=L^2;
                                                   // ②y=kx+b;
                                                   // 式中x,y即为根据以上lenthUnit单位长度(这里就是距离L)对应点的坐标
                                                   // 由①②表达式得到:(k^2+1)x^2+2[(b-y0)k-x0]x+[(b-y0)^2+x0^2-L^2]=0
            double A = Math.Pow(k, 2) + 1;// A=k^2+1;
            double B = 2 * ((b - curPoint.Y) * k - curPoint.X);// B=2[(b-y0)k-x0];
            //int m = 1;
            //double L = m * lenthUnit;
            // C=(b-y0)^2+x0^2-L^2
            double C = Math.Pow(b - curPoint.Y, 2) + Math.Pow(curPoint.X, 2)
                    - Math.Pow(L, 2);
            // 两根x1,x2= [-B±√(B^2-4AC)]/2A
            double x1 = (-B + Math.Sqrt(Math.Pow(B, 2) - 4 * A * C)) / (2 * A);
            double x2 = (-B - Math.Sqrt(Math.Pow(B, 2) - 4 * A * C)) / (2 * A);
            double x = 0;// 最后确定是在已知两点之间的某点
            if (x1 == x2)
            {
                x = x1;
            }
            else if (curPoint.X <= x1 && x1 <= nextPoint.X || nextPoint.X <= x1
                  && x1 <= curPoint.X)
            {
                x = x1;
            }
            else if (curPoint.X <= x2 && x2 <= nextPoint.X || nextPoint.X <= x2
                  && x2 <= curPoint.X)
            {
                x = x2;
            }
            double y = k * x + b;
            return new Point3d(x, y, 0);
        }

        #endregion

        #region 获取指定长度上的坐标点
        /// <summary>
        /// 获取指定长度上的坐标点
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="x2"></param>
        /// <param name="y1"></param>
        /// <param name="y2"></param>
        /// <param name="d"></param>
        /// <returns></returns>
        public static Point2d GetPointOnTheLine(Point2d pts,Point2d pte, double d)
        {
            double x1= pts.X;
            double y1= pts.Y;
            double x2=pte.X;
            double y2 = pte.Y;
            double r = Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
            //求 cy 可以根据d / a到b距离 = a到c垂直距离 / a 到 b的垂直距离。
            double cy = (d * (y2 - y1)) / r + y1;
            double cx = (d * (x2 - x1)) / r + x1;
            return new Point2d(cx, cy);
        }

        #endregion



        // 类方法计算两个点之间的距离
        public static double PointDistance(Point2d point1, Point2d point2)
        {
            return Math.Sqrt((Math.Pow((point1.X - point2.X), 2) + Math.Pow((point1.Y - point2.Y), 2)));
        }

        public static double PointDistance(Point3d point1, Point3d point2)
        {
            return Math.Sqrt((Math.Pow((point1.X - point2.X), 2) + Math.Pow((point1.Y - point2.Y), 2)) + Math.Pow((point1.Z - point2.Z), 2));
        }

    }
}
